package org.net5ijy.security.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

/**
 * 生成随机字符串验证码、图片工具类
 *
 * @author 创建人：xuguofeng
 * @version 创建于：2018年9月19日 上午8:29:27
 */
public class ValidateCodeUtil {

  private static char[] seq = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J',
      'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
      'Y', '3', '4', '5', '6', '7', '8', '9'};

  /**
   * 从默认字符集合生成指定长度的随机字符串
   *
   * @param length - 指定字符串的长度
   * @author 创建人：xuguofeng
   */
  public static String createValidateCode(Integer length) {
    return createValidateCode(length, seq);
  }

  /**
   * 从指定字符集合生成指定长度的随机字符串
   *
   * @param length - 指定字符串的长度
   * @param chs - 字符集合，随机字符串中的字符将从这个集合中获取。如果字符集合为null或长度为0，则使用默认字符集合
   * @author 创建人：xuguofeng
   */
  public static String createValidateCode(Integer length, char[] chs) {
    // 如果指定的字符集合为null或长度为0，则使用默认字符集合
    if (chs == null || chs.length < 1) {
      chs = seq;
    }
    StringBuilder builder = new StringBuilder();
    Random random = new Random();
    char ch;
    for (int i = 0; i < length; i++) {
      ch = seq[random.nextInt(seq.length)];
      builder.append(ch);
    }
    return builder.toString();
  }

  /**
   * 生成随机字符串图片
   *
   * @param width - 图片的宽度
   * @param height - 图片的高度
   * @param code - 随机字符串
   * @param lines - 干扰线的数量，默认为0
   * @param randomBg - 是否使用随机生成的背景颜色，默认白色
   * @author 创建人：xuguofeng
   */
  public static BufferedImage createImage(Integer width, Integer height,
      String code, Integer lines, boolean randomBg) {

    // 一些验证操作
    if (width <= 0 || height <= 0) {
      throw new RuntimeException(String.format("图片宽高不正确，宽[%s]，高[%s]",
          width, height));
    }
    if (code == null || code.length() <= 0) {
      throw new RuntimeException("字符串不合理: " + code);
    }

    Random random = new Random();

    // 创建指定宽高的图片对象
    BufferedImage image = new BufferedImage(width, height, 1);

    // 获取画笔
    Graphics g = image.getGraphics();

    if (randomBg) {
      // 随机生成背景颜色
      g.setColor(new Color(random.nextInt(255), random.nextInt(255),
          random.nextInt(255)));
    } else {
      // 默认的白色背景颜色
      g.setColor(new Color(255, 255, 255));
    }
    // 绘制背景
    g.fillRect(0, 0, width, height);

    // 绘制字符串
    for (int i = 0; i < code.length(); i++) {
      char ch = code.charAt(i);
      // 给该字符设置一个随机的颜色
      g.setColor(new Color(random.nextInt(255), random.nextInt(255),
          random.nextInt(255)));
      // 生成坐标
      int x = i * width / code.length() * 90 / 100;
      // double yy = random.nextDouble();
      double yy = 1;
      int y = (int) (height * 60 / 100 * yy + height * 30 / 100);
      // 字体
      g.setFont(new Font(null, Font.BOLD | Font.ITALIC, y));
      g.drawString(String.valueOf(ch), x, y);
    }

    // 绘制干扰线
    for (int i = 0; i < lines; i++) {
      // 随机的颜色
      g.setColor(new Color(random.nextInt(255), random.nextInt(255),
          random.nextInt(255)));
      g.drawLine(
          random.nextInt(width),
          random.nextInt(height),
          random.nextInt(width),
          random.nextInt(height));
    }
    // 关闭资源
    g.dispose();
    return image;
  }

  /**
   * 图片转为输入流
   *
   * @author 创建人：xuguofeng
   */
  public static InputStream createImageInputStream(BufferedImage image)
      throws IOException {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ImageIO.write(image, "JPEG", byteArrayOutputStream);
    return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
  }

  /**
   * 把图片输出到指定的输出流
   *
   * @param format - 指定格式，如JPEG
   * @author 创建人：xuguofeng
   */
  public static void out(BufferedImage image, OutputStream out, String format)
      throws IOException {
    ImageIO.write(image, format, out);
  }

  /**
   * 把图片输出到指定的输出流，使用JPEG格式
   *
   * @author 创建人：xuguofeng
   */
  public static void out(BufferedImage image, OutputStream out)
      throws IOException {
    out(image, out, "JPEG");
  }

  // public static void main(String[] args) throws IOException {
  // // String code = createValidateString(8);
  // // BufferedImage image = createImage(120, 30, code, 15, false);
  // // out(image, new FileOutputStream("d:\\code.jpg"));
  //
  // String code = createValidateCode(4);
  // BufferedImage image = createImage(80, 30, code, 15, false);
  // out(image, new FileOutputStream("d:\\code.jpg"));
  // }
}
